#include "ASprite.h"
#include "Game.h"

#include "System/Memory.h"
#include "System/Display.h"


// C Headers
#include <stdarg.h>
#include <stdio.h>

//#define		ARGB_2_RGB565(clr)    ((clr >> 8 ) & 0xf800) | ((clr >> 5 ) & 0x7e0) | ((clr >> 3 ) & 0x1f)
#define		FRM_OutIn_Count 4
#define		FRM_OutIn_Step 2

short GetShort(char* p, int * offset) {
	int pos = *offset;
	*offset = pos + 2;
	return (p[pos]&0xFF) + ((p[pos+1]&0xFF)<<8);
}

//void arraycopy( char * src, int srcPos, char * dest, int destPos, int length )
//{
//	MEMCPY( &dest[destPos], &src[srcPos], length * sizeof(char) );
//}
void ASprite::LoadImage(const char* filename)
{
	//if(_img)
	//{
		for(int i = 0 ; i < _img_num ; i++ )
		{
			getTexMgr()->Release(_img[i]);
		}
	//}
	//SAFE_DELETE( _img );
	_img_num = 1;
	_crt_img  = 0;
	//_img = GL_NEW T_U08[_img_num];
	_img[_crt_img] = LoadTexture(filename);
}

void ASprite::LoadSprite(char* filename)
{
	Read(filename, this);
}

void ASprite::LoadFile(void* object, CFileStream *pFS)
{
    ASprite *sprite = (ASprite*)object;

	if (pFS->getData() == NULL)
	{
		char *buff = GL_NEW char[pFS->miLength];
		pFS->Read(buff, pFS->miLength);
		sprite->Load(buff,0);
		SAFE_DELETE(buff);
	} else
	{
	    sprite->Load((char*)pFS->getData(),0);
	}
	//for(int i=0; i< sprite->_img_num; ++i)
	//{
	///	LoadTexture(sprite->_img[i]);
	//}
}

void ASprite::_ResetInit()
{
	_crt_img = 0;

	_current_animation = NULL;
	_current_frame = NULL;
	_current_frame_time = NULL;
	_is_looping = NULL;

	_nModules = 0;
#ifdef USE_BS_MODULES_IMG
	_modules_img_index = 0;
#endif
	_modules_x = NULL;
	_modules_y = NULL;
	_modules_w = NULL;
	_modules_h = NULL;
	//_modules_data_off = NULL;
	//_modules_data = NULL;
	_frames_nfm = NULL;
	_frames_fm_start = NULL;
	_frames_rc = NULL;
	_frames_coll = NULL;
	_fmodules = NULL;
	_anims_naf = NULL;
	_anims_af_start = NULL;
	_aframes = NULL;

#ifdef USE_MODULE_MAPPINGS
	_map = NULL;
#endif
	//_img = NULL;
	memset( _img, 0, sizeof(_img) );
	_bNeedFixed = false;

	_current_animation = GL_NEW int[MAX_ANIMATION_INSTANCES];
	memset( _current_animation, 0, sizeof(int)*MAX_ANIMATION_INSTANCES );
	_current_frame = GL_NEW int[MAX_ANIMATION_INSTANCES];
	memset( _current_frame, 0, sizeof(int)*MAX_ANIMATION_INSTANCES );
	_current_frame_time = GL_NEW int[MAX_ANIMATION_INSTANCES];
	memset( _current_frame_time, 0, sizeof(int)*MAX_ANIMATION_INSTANCES );
	_is_looping = GL_NEW bool[MAX_ANIMATION_INSTANCES];
	memset( _is_looping, 0, sizeof(bool)*MAX_ANIMATION_INSTANCES );
	_animState = 0;	

	for(int i=0;i < MAX_ANIMATION_INSTANCES; ++i)
	{
		SetCurrentAnimation(i,i,true);
	}
	_f_ox_if =0;
	_m_x_if =0;
	_f_oy_if =0;
	_m_y_if =0;

	_DrawObjSelectedCount = FRM_OutIn_Count;
	_objSelected = -1;

	m_cGame = gp_GameApp;
}

ASprite::ASprite(const int s, int palIdx, ...)
{
	_ResetInit();	
	_gfx = getGfx();

	va_list a;
	va_start(a,palIdx);
	_img_num = 0;
	int idx = palIdx;
	while( (idx >= 0) && (idx< MaxImgNum) ){
		ASSERT( _img_num < MaxImgNum );		
		//ASSERT(idx < (int)strlen((const char *) kBSpriteFile[s].num)/2);
		//_img[_img_num] = ((kBSpriteFile[s].num[idx*2]-1)|((kBSpriteFile[s].num[idx*2+1]-1)<<7))-1;// - kBSpriteFile[s].num[idx*2+1];
		LoadTexture(_img[_img_num]);
		_img_num++;
		idx = va_arg(a,int);
	};
	va_end(a);
	if( _img_num == 0 )
	{
		//_img_num = strlen((const char *) kBSpriteFile[s].num)/2;
		ASSERT( _img_num < MaxImgNum );	
		//_img = GL_NEW T_U08 [_img_num];
		for( int i = 0; i < _img_num; i++ )
		{
			//0_img[i] =((kBSpriteFile[s].num[i*2]-1)|((kBSpriteFile[s].num[i*2+1]-1)<<7))-1;//  - kBSpriteFile[s].num[i*2+1];
			//ASSERT(_img[i]<263);
			LoadTexture(_img[i]);
		}
	}
	//Read(kBSpriteFile[s].filename,this);
}
//ASprite::ASprite(const int s, const char* file)
//{
//	_ResetInit();
//	_gfx = getGfx();
//	if(file != NULL)
//	{
//		_img_num = 1;
//		_img = GL_NEW T_U08 [_img_num];
//		_img[0] = LoadTexture(file);
//	}
//	else
//	{
//		_img_num = STRLEN(kBSpriteFile[s].num);
//		_img = GL_NEW T_U08 [_img_num];
//		for( int i = 0; i < _img_num; i++ )
//		{
//			_img[i] = kBSpriteFile[s].num[i] - 1;
//			LoadTexture(_img[i]);
//		}
//	}
//	Read(kBSpriteFile[s].filename,this);
//}

ASprite::ASprite()
{
	_img_num = 0;
	_ResetInit();	
	_gfx = getGfx();
	_hasLoad = false;
}

ASprite::ASprite(const char *fname)
{
	_img_num = 0;
	_ResetInit();	
    Read(fname, this);	
	_gfx = getGfx();
}


void ASprite::clear()
{
	if(_hasLoad)
	{
		_hasLoad = false;
		SAFE_DELETE_ARRAY( _current_animation );
		SAFE_DELETE_ARRAY( _current_frame );
		SAFE_DELETE_ARRAY( _current_frame_time );
		SAFE_DELETE_ARRAY( _is_looping );

		SAFE_DELETE_ARRAY( _modules_x );
		SAFE_DELETE_ARRAY( _modules_y );
	#ifdef USE_BS_MODULES_IMG
		SAFE_DELETE_ARRAY( _modules_img_index );
	#endif
		SAFE_DELETE_ARRAY( _modules_w );
		SAFE_DELETE_ARRAY( _modules_h );
		SAFE_DELETE_ARRAY( _frames_nfm );
		SAFE_DELETE_ARRAY( _frames_fm_start );
		SAFE_DELETE_ARRAY( _frames_rc );
		SAFE_DELETE_ARRAY( _frames_coll );
		SAFE_DELETE_ARRAY( _fmodules );
		SAFE_DELETE_ARRAY( _anims_naf );
		SAFE_DELETE_ARRAY( _anims_af_start );
		SAFE_DELETE_ARRAY( _aframes );

	#ifdef USE_MODULE_MAPPINGS
		if(_map)
		{
			for( int i = 0 ; i < MAX_MODULE_MAPPINGS ; i++ )
			{
				SAFE_DELETE_ARRAY(_map[i]);
			}
			SAFE_DELETE_ARRAY( _map );
		}
	#endif

 		//if(_img)
 		//{
 			for(int i = 0 ; i < _img_num ; i++ )
			{
				getTexMgr()->Release(_img[i]);
				_img[i] = NULL;
 			}
		//}
		//SAFE_DELETE( _img );

		//SAFE_DELETE_ARRAY( _modules_data_off ) ;
		//SAFE_DELETE_ARRAY( _modules_data ) ;	
	}
};

ASprite::~ASprite()
{
	clear();
}

void ASprite::Load(char * file, int offset)
{
	ASSERT( file );
	_hasLoad = true;

	/*short bs_version = (short)((file[offset]&0xFF) + ((file[offset+1]&0xFF)<<8));
	offset +=2 ;


	int bs_flags =  ((file[offset]&0xFF)) +
            ((file[offset+1]&0xFF)<< 8) +
            ((file[offset+2]&0xFF)<<16) +
            ((file[offset+3]&0xFF)<<24);
			offset += 4 ;*/

	_nModules = (file[offset]&0xFF) + ((file[offset+1]&0xFF)<<8);
	offset += 2 ;

	if( _nModules > 0 )
	{
#ifdef USE_BS_MODULES_IMG
		_modules_img_index = GL_NEW T_U08[_nModules];
#endif
		_modules_x = GL_NEW short [_nModules]; //whoJu+
		_modules_y = GL_NEW short [_nModules];
		_modules_w = GL_NEW short [_nModules];
		_modules_h = GL_NEW short [_nModules];
		for( int i = 0; i < _nModules; i++ )
		{
#ifdef USE_BS_MODULES_IMG
			_modules_img_index[i] = file[offset]&0xff;
			offset += 1;
#endif
			_modules_x[i] = GetShort( file, &offset );
			_modules_y[i] = GetShort( file, &offset );//file[offset++];
			_modules_w[i] = GetShort( file, &offset );
			_modules_h[i] = GetShort( file, &offset );
		}
	}

	int nFModules = (file[offset]&0xFF) + ((file[offset+1]&0xFF)<<8);
	offset += 2 ;

	if (nFModules > 0)
	{
		int len = nFModules * 6;
		_fmodules = GL_NEW T_S08 [len];
		MEMCPY( &_fmodules[0], &file[offset], len * sizeof(T_S08) );
		offset += len;
	}

	int nFrames = (file[offset]&0xFF) + ((file[offset+1]&0xFF)<<8);
	offset += 2 ;

	if( nFrames > 0 )
	{
		_nFrames = nFrames;
		_frames_nfm = GL_NEW char[nFrames];
		_frames_fm_start = GL_NEW short[nFrames];

		for( int i = 0; i < nFrames; i++ )
		{
			_frames_nfm[i] = file[offset++];
//#ifndef ALWAYS_BS_NFM_1_BYTE
//			offset++;
//#endif
			_frames_fm_start[i] = (short)((file[offset]&0xFF) + ((file[offset+1]&0xFF)<<8));
			offset += 2 ;
		}

//#ifndef ALWAYS_BS_SKIP_FRAME_RC
//                if ((bs_flags & BS_SKIP_FRAME_RC) != BS_SKIP_FRAME_RC) {
//#ifdef USE_PRECOMPUTED_FRAME_RECT
//                    {
                        int nFrames4 = nFrames<<2;
                        _frames_rc = GL_NEW char[nFrames4];
                        for (int i = 0; i < nFrames4; i++)
                            _frames_rc[i] = file[offset++];
//                    }
//#else
//                        offset += (nFrames<<2);
//#endif
//                }
//#endif

//#ifndef ALWAYS_BS_FRAME_COLL_RC
//            {
//                if ((bs_flags & BS_FRAME_COLL_RC) == BS_FRAME_COLL_RC) {
//                    //if (DEF::bDbgS) System.out.println("use BS_FRAME_COLL_RC");
//
//                    int nFrames4 = nFrames<<2;
//                    _frames_coll = GL_NEW char[nFrames4];
//                    for (int i = 0; i < nFrames4; i++)
//                        _frames_coll[i] = file[offset++];
//                }
//            }
//#endif
        }

        int nAFrames = (file[offset]&0xFF) + ((file[offset+1]&0xFF)<<8);
		offset += 2 ;
        if (nAFrames > 0)
        {
			int len = nAFrames * 5 ;
            _aframes = GL_NEW T_S08[len];
			MEMCPY( &_aframes[0], &file[offset], len * sizeof(T_S08) );
            offset += len;
        }

        _nAnims = (file[offset]&0xFF) + ((file[offset+1]&0xFF)<<8);
		offset += 2 ;
        if( _nAnims > 0 )
        {
            _anims_naf      = GL_NEW  T_S08[_nAnims];
            _anims_af_start = GL_NEW short[_nAnims];

            for (int i = 0; i < _nAnims; i++)
            {
                _anims_naf[i]      = (T_S08)file[offset++];
//#ifndef ALWAYS_BS_NAF_1_BYTE
//					offset++;
//#endif

                _anims_af_start[i] = (short)((file[offset]&0xFF) + ((T_S08)(file[offset+1]&0xFF)<<8));
				offset += 2 ;
            }

        }

        if (_nModules <= 0)
        {
           return;
        }
}

//void ASprite::ClearTemporaryBuffer()
//{
//	//delete[] temp ;
//    //temp = NULL;
//}

int ASprite::GetAFrameTime(int anim, int aframe)
{
    return _aframes[(_anims_af_start[anim] + aframe) * 5 + 1] & 0xFF;
}

int ASprite::GetAFrames(int anim)
{
    return _anims_naf[anim]&0xFF;
}

int ASprite::GetFModules(int frame)
{
    return _frames_nfm[frame]&0xFF;
}

int ASprite::GetModuleWidth(int module)
{
    return _modules_w[module]&0xFFFF;
}

int ASprite::GetModuleHeight(int module)
{
    return _modules_h[module]&0xFFFF;
}

int ASprite::GetFrameWidth(int frame)
{
    return _frames_rc[frame*4 + 2]&0xFF;
}

int ASprite::GetFrameHeight(int frame)
{
    return _frames_rc[frame*4 + 3]&0xFF;
}


int ASprite::GetFrameCollisionLeft(int frame)
{
    return _frames_coll[frame*4 + 0];
}

int ASprite::GetFrameCollisionTop(int frame)
{
    return _frames_coll[frame*4 + 1];
}

int ASprite::GetFrameCollisionRight(int frame)
{
    return _frames_coll[frame*4 + 2];
}

int ASprite::GetFrameCollisionBottom(int frame)
{
    return _frames_coll[frame*4 + 3];
}


int ASprite::GetFrameModuleX(int frame, int fmodule)
{
	//laevo: 20061206 _fmodules is BS_FM_OFF_SHORT
    int off = (_frames_fm_start[frame] + fmodule) * 6; //<<2;
    //int off = (_frames_fm_start[frame] + fmodule) << 2;
    return (_fmodules[off + 1] & 0xFF) | ((_fmodules[off + 2] & 0xFF) << 8);
}

int ASprite::GetFrameModuleY(int frame, int fmodule)
{
	//laevo: 20061206 _fmodules is BS_FM_OFF_SHORT
    int off = (_frames_fm_start[frame] + fmodule) * 6; //<<2;
    //int off = (_frames_fm_start[frame] + fmodule) << 2;
    return (_fmodules[off + 3] & 0xFF) | ((_fmodules[off + 4] & 0xFF) << 8);
}

int ASprite::GetFrameModuleWidth(int frame, int fmodule)
{
	//laevo: 20061206 _fmodules is BS_FM_OFF_SHORT
    int off = (_frames_fm_start[frame] + fmodule) * 6; //<<2;
    int index = _fmodules[off]&0xFF;
    return _modules_w[index]&0xFFFF;
}

int ASprite::GetFrameModuleHeight(int frame, int fmodule)
{
    //laevo: 20061206 _fmodules is BS_FM_OFF_SHORT
    int off = (_frames_fm_start[frame] + fmodule) * 6; //<<2;
    int index = _fmodules[off]&0xFF;
    return _modules_h[index]&0xFFFF;
}


int ASprite::GetAnimFrame(int anim, int aframe)
{
    int off = (_anims_af_start[anim] + aframe) * 5;
    return _aframes[off]&0xFF;
}


void ASprite::GetAFrameRect(int * rc, int anim, int aframe, int posX, int posY, int flags, int hx, int hy)
{
    int off = (_anims_af_start[anim] + aframe) * 5;
    int frame = _aframes[off]&0xFF;
#ifdef USE_INDEX_EX_AFRAMES
        frame |= ((_aframes[off+4]&FLAG_INDEX_EX_MASK)<<INDEX_EX_SHIFT);
#endif
    if ((flags & FLAG_OFFSET_AF) != 0)
    {
        if ((flags & FLAG_FLIP_X) != 0)
			hx += _aframes[off+2];
        else
			hx -= _aframes[off+2];
        if ((flags & FLAG_FLIP_Y) != 0)
			hy += _aframes[off+3];
        else
			hy -= _aframes[off+3];
    }

    GetFrameRect(rc, frame, posX, posY, flags ^ (_aframes[off+4]&0x0F), hx, hy);
}



void ASprite::GetFrameRect(int * rc, int frame, int posX, int posY, int flags, int hx, int hy)
{
#ifdef USE_PRECOMPUTED_FRAME_RECT
    {
        int frame4 = frame<<2;
        int fx = _frames_rc[frame4++];
        int fy = _frames_rc[frame4++];
        int fw = _frames_rc[frame4++]&0xFF;
        int fh = _frames_rc[frame4++]&0xFF;

        if ((flags & FLAG_FLIP_X) != 0)
			hx += fx + fw;
        else
			hx -= fx;
        if ((flags & FLAG_FLIP_Y) != 0)
			hy += fy + fh;
        else
			hy -= fy;

        rc[0] = posX - (hx << FIXED_PRECISION);
        rc[1] = posY - (hy << FIXED_PRECISION);
        rc[2] = rc[0] + (fw << FIXED_PRECISION);
        rc[3] = rc[1] + (fh << FIXED_PRECISION);
    }
#else
    {
        int fx = 0;
        int fy = 0;
        int fw = 0;
        int fh = 0;

        int nFModules = _frames_nfm[frame]&0xFF;

        for (int fmodule = 0; fmodule < nFModules; fmodule++)
        {
            GetFModuleRect(rc, frame, fmodule, posX, posY, flags, hx, hy);

            if (rc[0] < fx)
            {
                fw = (fx+fw) - rc[0];
                fx = rc[0];
            }

            if (rc[1] < fy)
            {
                fh = (fy+fh) - rc[1];
                fy = rc[1];
            }

            if (rc[2] > fx + fw)
            {
                fw = rc[2] - fx;
            }

            if (rc[3] > fy + fh)
            {
                fh = rc[3] - fy;
            }
        }

        hx <<= FIXED_PRECISION;
        hy <<= FIXED_PRECISION;

        if ((flags & FLAG_FLIP_X) != 0)
			hx += fx + fw;
        else
			hx -= fx;
        if ((flags & FLAG_FLIP_Y) != 0)
			hy += fy + fh;
        else
			hy -= fy;

        rc[0] = posX - hx;
        rc[1] = posY - hy;
        rc[2] = rc[0] + fw;
        rc[3] = rc[1] + fh;
    }
#endif
}

void ASprite::GetFModuleRect(int * rc, int frame, int fmodule, int posX, int posY, int flags, int hx, int hy)
{
    rc[0] = GetFrameModuleX(frame, fmodule) << FIXED_PRECISION;
    rc[1] = GetFrameModuleY(frame, fmodule) << FIXED_PRECISION;
    rc[2] = rc[0] + (GetFrameModuleWidth(frame, fmodule) << FIXED_PRECISION);
    rc[3] = rc[1] + (GetFrameModuleHeight(frame, fmodule) << FIXED_PRECISION);
}

void ASprite::GetModuleRect(int * rc, int module, int posX, int posY, int flags)
{
    rc[0] = posX;
    rc[1] = posY;
    rc[2] = posX + ((_modules_w[module]&0xFFFF) << FIXED_PRECISION);
    rc[3] = posY + ((_modules_h[module]&0xFFFF) << FIXED_PRECISION);
}

void ASprite::SetCurrentAnimation(int anim, bool loop)
{
    SetCurrentAnimation(anim, anim, loop);
}

void ASprite::SetCurrentAnimation(int animIndex, int anim, bool loop ,int startFrame)
{
#ifdef _DEBUG
    if (animIndex >= MAX_ANIMATION_INSTANCES) {
        //if (DEF::bDbgS) System.out.println("MAX_ANIMATION_INSTANCES is too small!");
    }
#endif
    _current_animation[animIndex] = anim;
    _current_frame[animIndex] = startFrame;
    _current_frame_time[animIndex] = 0;
    _is_looping[animIndex] = loop;
}

int ASprite::GetCurrentAnimation()
{
    return GetCurrentAnimation(0);
}

int ASprite::GetCurrentAnimation(int animIndex)
{
#ifdef _DEBUG
	ASSERT( animIndex < MAX_ANIMATION_INSTANCES );
	//if (animIndex >= MAX_ANIMATION_INSTANCES) {
	//	//if (DEF::bDbgS) System.out.println("MAX_ANIMATION_INSTANCES is too small!");
	//}
#endif
    return _current_animation[animIndex];
}

int ASprite::GetCurrentAnimationFrame()
{
    return GetCurrentAnimationFrame(0);
}

int ASprite::GetCurrentAnimationFrame(int animIndex) {
	return _aframes[(_anims_af_start[_current_animation[animIndex]] + _current_frame[animIndex]) * 5];
}

int ASprite::GetAnimationFrameIndex(int animIndex)
{
	return _current_frame[animIndex];
}

/*
int ASprite::PaintAndUpdateCurrentAnimation(int posX, int posY, int flags, int hx, int hy)
{
    return PaintAndUpdateCurrentAnimation(g, 0, posX, posY, flags, hx, hy);
}
*/

int ASprite::PlayAnim(int animIndex, int posX, int posY, int flags, int hx, int hy)
{
#ifdef _DEBUG
	ASSERT( animIndex < _nAnims );
	ASSERT( animIndex >= MAX_ANIMATION_INSTANCES );
	//if (animIndex >= MAX_ANIMATION_INSTANCES) {
	//	//if (DEF::bDbgS) System.out.println("MAX_ANIMATION_INSTANCES is too small!");
	//}
#endif

	int off = (_anims_af_start[_current_animation[animIndex]] + _current_frame[animIndex]) * 5;
	int frame = _aframes[off] & 0xFF;

#ifdef USE_INDEX_EX_AFRAMES
	frame |= ((_aframes[off + 4] & FLAG_INDEX_EX_MASK) << INDEX_EX_SHIFT);
#endif

	if ((flags & FLAG_FLIP_X) != 0)
		hx += _aframes[off + 2];
	else
		hx -= _aframes[off + 2];
	if ((flags & FLAG_FLIP_Y) != 0)
		hy += _aframes[off + 3];
	else
		hy -= _aframes[off + 3];

	PaintFrame( frame, posX - hx, posY - hy, flags ^ (_aframes[off + 4] & 0x0F), hx, hy);

	if( _animState == ANIM_PLAYING )
	{
		if(++_current_frame_time[animIndex] >= (_aframes[off + 1] & 0xFF))
		{
			if(++_current_frame[animIndex] >= (_anims_naf[_current_animation[animIndex]] & 0xFF))
			{
				if(_is_looping[animIndex])
				{
					_current_frame_time[animIndex] = 0;
					_current_frame[animIndex] = 0;
				}
				else
				{
					_current_frame[animIndex]--;
				}
			}
			else
			{
				_current_frame_time[animIndex] = 0;
			}
		}
	}

	return _current_frame[animIndex];
}

void ASprite::StartAnim(int animIndex, bool bLoop)
{
	_current_frame_time[animIndex] = 0;
	_current_frame[animIndex] = 0;
	//_is_looping[animIndex] = bLoop;
	_animState = ANIM_PLAYING;
}

void ASprite::PauseAnim(int animIndex)
{
	_animState = ANIM_PAUSED;
}

void ASprite::ResumeAnim(int animIndex, bool bLoop)
{
	//_is_looping[animIndex] = bLoop;
	_animState = ANIM_PLAYING;
}

void ASprite::StopAnim(int animIndex)
{
	_current_frame_time[animIndex] = 0;
	_current_frame[animIndex] = 0;
	_animState = ANIM_STOP;
}

bool ASprite::IsFreeAnim(int animIndex)
{
	return _current_frame[animIndex] == 0?true:false;
}

void ASprite::UpdateAnimation(int animIndex)
{
    int off = (_anims_af_start[_current_animation[animIndex]] + _current_frame[animIndex]) * 5;


    if(++_current_frame_time[animIndex] >= (_aframes[off + 1] & 0xFF))
    {
        if(++_current_frame[animIndex] >= (_anims_naf[_current_animation[animIndex]] & 0xFF))
        {
            if(_is_looping[animIndex])
            {
                _current_frame_time[animIndex] = 0;
                _current_frame[animIndex] = 0;
            }
            else
            {
                _current_frame[animIndex]--;
            }
        } else {
            _current_frame_time[animIndex] = 0;
        }
    }	
}

int ASprite::PaintAndUpdateCurrentAnimation(int animIndex, float posX, float posY, int flags, int hx, int hy)
{
#ifdef _DEBUG
    if (animIndex >= MAX_ANIMATION_INSTANCES) {
        //if (DEF::bDbgS) System.out.println("MAX_ANIMATION_INSTANCES is too small!");
    }
#endif

    int off = (_anims_af_start[_current_animation[animIndex]] + _current_frame[animIndex]) * 5;
    int frame = _aframes[off] & 0xFF;

#ifdef USE_INDEX_EX_AFRAMES
	frame |= ((_aframes[off + 4] & FLAG_INDEX_EX_MASK) << INDEX_EX_SHIFT);
#endif //USE_INDEX_EX_AFRAMES

    if ((flags & FLAG_FLIP_X) != 0)
		hx += _aframes[off + 2];
    else
		hx -= _aframes[off + 2];
    if ((flags & FLAG_FLIP_Y) != 0)
		hy += _aframes[off + 3];
    else
		hy -= _aframes[off + 3];

    PaintFrame( frame, posX - hx, posY - hy, flags ^ (_aframes[off + 4] & 0x0F), hx, hy );
	//PaintFrameIn2D( frame, posX - hx, posY - hy, flags ^ (_aframes[off + 4] & 0x0F), hx, hy );

    if(++_current_frame_time[animIndex] >= (_aframes[off + 1] & 0xFF))
    {
        if(++_current_frame[animIndex] >= (_anims_naf[_current_animation[animIndex]] & 0xFF))
        {
            if(_is_looping[animIndex])
            {
                _current_frame_time[animIndex] = 0;
                _current_frame[animIndex] = 0;
            }
            else
            {
                _current_frame[animIndex]--;
            }
        } else {
            _current_frame_time[animIndex] = 0;
        }
    }

    return _current_frame[animIndex];
}

bool ASprite::IsAnimationDone()
{
    return IsAnimationDone(0);
}

bool ASprite::IsAnimationDone(int animIndex) {
	ASSERT(animIndex < MAX_ANIMATION_INSTANCES);
    int off = (_anims_af_start[_current_animation[animIndex]] + _current_frame[animIndex]) * 5;
    return /*!_is_looping[animIndex] &&*/ (_current_frame[animIndex] + 1 == (_anims_naf[_current_animation[animIndex]] & 0xFF))/* && (_current_frame_time[animIndex] >= (_aframes[off + 1] & 0xFF))*/;
}
bool ASprite::IsAnimationDone2(int animIndex) {
	ASSERT(animIndex < MAX_ANIMATION_INSTANCES);
	int off = (_anims_af_start[_current_animation[animIndex]] + _current_frame[animIndex]) * 5;
	return /*!_is_looping[animIndex] &&*/ (_current_frame[animIndex] + 1 == (_anims_naf[_current_animation[animIndex]] & 0xFF)) && (_current_frame_time[animIndex] >= (_aframes[off + 1] & 0xFF));
}

void ASprite::PaintAniOutIn(int anim, int posX, int posY, T_F32 inScale)
{
	int off = (_anims_af_start[_current_animation[anim]]) * 5;
	int frame = _aframes[off] & 0xFF;

	if( (_objSelected != frame) && (_DrawObjSelectedCount == FRM_OutIn_Count) )
	{
		_DrawObjSelectedCount = -10;
		_objSelected = frame;
	}

	T_F32 _scale = inScale;
	if( _DrawObjSelectedCount < FRM_OutIn_Count )
	{		
		_scale = inScale * (1.2f - CMath::Abs(_DrawObjSelectedCount) / 20.0f);
		_DrawObjSelectedCount += FRM_OutIn_Step;
		GFX_SetScale( _scale, _scale );
		PaintFrame( frame, posX, posY );		
	}
	else
	{
		GFX_SetScale( _scale, _scale );
		PaintAndUpdateCurrentAnimation( anim, posX, posY );
	}
	GFX_ResetScale();
}

void ASprite::PaintAFrame(int anim, int aframe, int posX, int posY, int flags, int hx, int hy)
{
    int off = (_anims_af_start[anim] + aframe) * 5;
    int frame = _aframes[off] & 0xFF;

#ifdef USE_INDEX_EX_AFRAMES
	frame |= ((_aframes[off + 4] & FLAG_INDEX_EX_MASK) << INDEX_EX_SHIFT);
#endif //USE_INDEX_EX_AFRAMES

    if ((flags & FLAG_FLIP_X) != 0)
		hx += _aframes[off + 2];
    else
		hx -= _aframes[off + 2];
    if ((flags & FLAG_FLIP_Y) != 0)
		hy += _aframes[off + 3];
    else
		hy -= _aframes[off + 3];

    PaintFrame( frame, posX - hx, posY - hy, flags ^ (_aframes[off + 4] & 0x0F), hx, hy);
}

#ifdef _OptimizePaintFrame
void ASprite::PaintFrame(T_S32 frame, T_F32 posX, T_F32 posY, T_S32 flags, T_S32 hx, T_S32 hy)
{	
	if( (frame < 0) || (frame > _nFrames) ) return;
	BeginBatchFrm( posX, posY );
	AddFrm( frame, 0, 0, flags, hx, hy );
	EndBatchFrm();	
}

void ASprite::PaintFlashFrame(int frame, int posX, int posY, int flags, int hx, int hy)
{
	//PaintFrame( TEXTBAR_FRAME_PRESSED +  frame, posX, posY, flags, hx, hy );
	if(true)
	{
		int w = GetFrameWidth( frame );
		int h = GetFrameHeight( frame );
		getGfx()->SetColor( 0x3fffffff);
		getGfx()->FillRect( posX-w/2,posY-h/2,w, h);	
	}
}

void ASprite::PaintBlinkFrame(int frame, int posX, int posY, int flags, int hx, int hy)
{
	PaintFrame( frame, posX, posY, flags, hx, hy );
	
	int w = GetFrameWidth( frame );
	int h = GetFrameHeight( frame );

	//getGfx()->SetColor( 0x5fffffff + (((gp_GameApp->miFrameCounter/3)%5)<<27) );
	getGfx()->SetColor( TO_ARGB((CMath::Abs(gp_GameApp->miFrameCounter) % 4 < 2)? 0x00: 0xee, 0xff, 0xff, 0xff) );
	getGfx()->FillRect( posX-w/2,posY-h/2,w, h);	
	
}

void ASprite::PaintFlashModule(int module, int posX, int posY, int flags)
{
	PaintModule( module, posX, posY, flags);

	int w = GetModuleWidth( module );
	int h = GetModuleHeight( module );
	getGfx()->SetColor( 0x5fffffff);
	getGfx()->FillRect( posX,posY,w, h);
}

void ASprite::BeginBatchFrm(T_F32 x, T_F32 y)
{
	g2DCommRI.destX = x;
	g2DCommRI.destY = y;
	gRenderQI.count = 0;
}
//void ASprite::AddFModule2(T_S32 frame, T_S32 indexf, T_S32 posX, T_S32 posY, T_S32 flags, T_S32 hx, T_S32 hy)
//{
//	GLfloat tL, tB, tR,tT, vL,vB, vR, vT;
//	//@brief frame offset is short type
//	int off = (_frames_fm_start[frame] + indexf - JAPANESE_MD_0X2026) * 6; // laevo: BS_FM_OFF_SHORT
//	int fm_flags = _fmodules[off+5]&0xFF;
//	//laevo:M 20070716
//	//@brief 1L is for breaking the limit of module num per frame (less 256)
//	//          but must fmodule index agree with module index. (for example jp font index)
//	int index = indexf;
//	int ox = (_fmodules[off + 1] & 0xFF) | ((_fmodules[off + 2]) << 8);
//	int oy = (_fmodules[off + 3] & 0xFF) | ((_fmodules[off + 4]) << 8);
//
//	int target_dx = posX;
//	int target_dy = posX;
//	if( (flags & FLAG_FLIP_X) != 0 )
//		ox = -ox - _modules_w[index]&0xFFFF;
//	if ((flags & FLAG_FLIP_Y) != 0 )
//		oy = -oy - _modules_h[index]&0xFFFF;
//	int _flags = flags;
//	_flags ^= (fm_flags&0x0F);
//
//	int modX = _modules_x[index]&0xFFFF;
//	int modY = _modules_y[index]&0xFFFF;
//	int modW = _modules_w[index]&0xFFFF;
//	int modH = _modules_h[index]&0xFFFF;
//	if( modW <= 0 || modH <= 0 ) return;
//	if( _img_num*_nModules < _crt_img * _nModules + index )
//		return;
//
//	int target_mw = modW;
//	int target_mh = modH;
//	if( _flags & FLAG_ROT_90 )
//	{
//		target_mw = modH;
//		target_mh = modW;
//	}
//
//	int _offsetL = hx;
//	int _offsetB = hy-target_mh;
//	int _offsetR = hx+target_mw;
//	int _offsetT = hy;
//
//	/*if( g2DCommRI.anchorType == Is_Center_LT2HV )
//	{
//	_offsetL = -target_mw/2;
//	_offsetB = -target_mh/2;
//	_offsetR = -_offsetL;
//	_offsetT = -_offsetB;
//	}*/
//	/*if( _bNeedFixed && (g2DCommRI.transform&IS_ROT) )
//	{
//		modW++; modH++;
//	}*/
//
//	ox += posX;
//	oy += posY;
//
//	vL = IPLMath_IntToFixed(  ox + _offsetL );
//	vB = IPLMath_IntToFixed( -oy + _offsetB );
//	vR = IPLMath_IntToFixed(  ox + _offsetR );
//	vT = IPLMath_IntToFixed( -oy + _offsetT );
//
//	//GLfloat autoZ = 0;
//	GLfloat vertices[] =
//	{
//#ifdef ENABLE_QUADS
//		vL, vB, 0,	// Left-Bottom
//		vL, vT, 0,	// Left-Top
//		vR, vT, 0,	// Right-Top
//		vR, vB, 0,	// Right-Bottom
//#else
//		vL, vT, 0,  // Left-Top
//		vL, vB, 0,  // Left-Bottom
//		vR, vB, 0,  // Right-Bottom
//		vL, vT, 0,  // Left-Top
//		vR, vB, 0,  // Right-Bottom
//		vR, vT, 0,  // Right-Top
//#endif
//	};
//
//	//tL = IPLMath_IntToFixed( modX );
//	//tT = IPLMath_IntToFixed( modY );
//	//tR = IPLMath_IntToFixed( modX + modW);
//	//tB = IPLMath_IntToFixed( modY + modH);
//
//	TexInfo * pInfo = (TexInfo*)getTexMgr()->GetTex( _img[_crt_img] );
//	
//	tL = (float)modX / (float)pInfo->width;
//	tT = (float)modY / (float)pInfo->height;
//	tR = (float)(modX + modW) / (float)pInfo->width;
//	tB = (float)(modY + modH) / (float)pInfo->height;
//
//	GLfloat texCoord[] =
//	{
//#ifdef ENABLE_QUADS
//		tL, tB,
//		tL, tT,
//		tR, tT,
//		tR, tB
//#else
//		tL, tT,
//		tL, tB,
//		tR, tB,
//		tL, tT,
//		tR, tB,
//		tR, tT,
//#endif
//	};
//	
//	if( _flags & FLAG_ROT_90 )
//	{
//		//Change vertices order
//		vertices[0] = vR;
//		vertices[1] = vT;
//		vertices[3] = vL;
//		vertices[4] = vT;
//		vertices[6] = vL;
//		vertices[7] = vB;
//
//		vertices[9] = vR;
//		vertices[10] = vT;
//		vertices[12] = vL;
//		vertices[13] = vB;
//		vertices[15] = vR;
//		vertices[16] = vB;
//	}
//
//	if( _flags & FLAG_FLIP_X )
//	{
//		texCoord[0] = texCoord[2] = texCoord[6] = tR;
//		texCoord[4] = texCoord[8] = texCoord[10] = tL;
//	}
//	if( _flags & FLAG_FLIP_Y )
//	{
//		texCoord[3] = texCoord[5] = texCoord[9] = tT;
//		texCoord[1] = texCoord[7] = texCoord[11] = tB;
//	}
//
//#ifdef IPL_HAVE_MESSED_UP_QUADS
//	GLfloat _tempX, _tempY;
//	_tempX = texCoord[4]; texCoord[4] = texCoord[6]; texCoord[6] = _tempX;
//	_tempY = texCoord[5]; texCoord[5] = texCoord[7]; texCoord[7] = _tempY;
//#endif
//	int pos = gRenderQI.count*6*3;
//	MEMCPY( gRenderQI.v + pos, vertices, sizeof(vertices) );
//	pos = gRenderQI.count*6*2;
//	MEMCPY( gRenderQI.t + pos, texCoord, sizeof(texCoord) );
//	gRenderQI.count++;
//}
void ASprite::AddFModule(T_S32 frame, T_S32 indexf, T_S32 posX, T_S32 posY, T_S32 flags, T_S32 hx, T_S32 hy)
{
	GLfloat tL, tB, tR,tT, vL,vB, vR, vT;
	
	// frame offset is short type
	int off = (_frames_fm_start[frame] + indexf) * 6; // laevo: BS_FM_OFF_SHORT
	int fm_flags = _fmodules[off+5]&0xFF;
	
	// 1L is for breaking the limit of module num per frame (less 256)
	// but must fmodule index agree with module index. (for example jp font index)
	int index = (indexf>255)?(indexf):(_fmodules[off]&0xFF);
	int ox = (_fmodules[off + 1] & 0xFF) | ((_fmodules[off + 2]) << 8);
	int oy = (_fmodules[off + 3] & 0xFF) | ((_fmodules[off + 4]) << 8);

	if( (flags & FLAG_FLIP_X) != 0 )
		ox = -ox - (int)(_modules_w[index]&0xFFFF);
	if ((flags & FLAG_FLIP_Y) != 0 )
		oy = -oy - (int)(_modules_h[index]&0xFFFF);
	
	int _flags = flags;
	_flags ^= (fm_flags&0x0F);

	int modX = _modules_x[index]&0xFFFF;
	int modY = _modules_y[index]&0xFFFF;
	int modW = _modules_w[index]&0xFFFF;
	int modH = _modules_h[index]&0xFFFF;
	if( modW <= 0 || modH <= 0 ) return;

	int target_mw = modW;
	int target_mh = modH;
	if( _flags & FLAG_ROT_90 )
	{
		target_mw = modH;
		target_mh = modW;
	}

	int _offsetL = hx;
	int _offsetB = hy-target_mh;
	int _offsetR = hx+target_mw;
	int _offsetT = hy;

	/*if( g2DCommRI.anchorType == Is_Center_LT2HV )
	{
		_offsetL = -target_mw/2;
		_offsetB = -target_mh/2;
		_offsetR = -_offsetL;
		_offsetT = -_offsetB;
	}*/
	
	ox += posX;
	oy += posY;

	vL = IPLMath_IntToFixed(  ox + _offsetL );
	vB = IPLMath_IntToFixed( -oy + _offsetB );
	vR = IPLMath_IntToFixed(  ox + _offsetR );
	vT = IPLMath_IntToFixed( -oy + _offsetT );

	vL = vL * TALL_BY_METERS * RATIO_SCREEN/ SCREEN_WIDTH;
	vB = vB * TALL_BY_METERS/ SCREEN_HEIGHT;
	vR = vR * TALL_BY_METERS * RATIO_SCREEN/ SCREEN_WIDTH;
	vT = vT * TALL_BY_METERS/ SCREEN_HEIGHT;
	GLfloat vertices[] =
	{
#ifdef ENABLE_QUADS
		vL, vB, 0,	// Left-Bottom
		vL, vT, 0,	// Left-Top
		vR, vT, 0,	// Right-Top
		vR, vB, 0,	// Right-Bottom
#else
		vL, vT, 0,  // Left-Top
		vL, vB, 0,  // Left-Bottom
		vR, vB, 0,  // Right-Bottom
		vL, vT, 0,  // Left-Top
		vR, vB, 0,  // Right-Bottom
		vR, vT, 0,  // Right-Top
#endif
	};

	if( _bNeedFixed && (g2DCommRI.transform&IS_ROT) )
	{
		modW++; modH++;
	}

	TexInfo * pInfo = (TexInfo*)getTexMgr()->GetTex( _img[_crt_img] );
	
	tL = (float)modX / (float)pInfo->width;
	tT = (float)modY / (float)pInfo->height;
	tR = (float)(modX + modW) / (float)pInfo->width;
	tB = (float)(modY + modH) / (float)pInfo->height;


	GLfloat texCoord[] =
	{
#ifdef ENABLE_QUADS
		tL, tB,
		tL, tT,
		tR, tT,
		tR, tB
#else
		tL, tT,
		tL, tB,
		tR, tB,
		tL, tT,
		tR, tB,
		tR, tT,
#endif
	};

	if( _flags & FLAG_ROT_90 )
	{
		//Change vertices order
		vertices[0] = vR;
		vertices[1] = vT;
		vertices[3] = vL;
		vertices[4] = vT;
		vertices[6] = vL;
		vertices[7] = vB;

		vertices[9] = vR;
		vertices[10] = vT;
		vertices[12] = vL;
		vertices[13] = vB;
		vertices[15] = vR;
		vertices[16] = vB;
	}

	if( _flags & FLAG_FLIP_X )
	{
		texCoord[0] = texCoord[2] = texCoord[6] = tR;
		texCoord[4] = texCoord[8] = texCoord[10] = tL;
	}
	if( _flags & FLAG_FLIP_Y )
	{
		texCoord[3] = texCoord[5] = texCoord[9] = tT;
		texCoord[1] = texCoord[7] = texCoord[11] = tB;
	}


	// RUIZD: 6 verts of 3 component
	int pos = gRenderQI.count*6*3;
	MEMCPY( gRenderQI.v + pos, vertices, sizeof(vertices) );
	// RUIZD: 6 verts of 2 component
	pos = gRenderQI.count*6*2;
	MEMCPY( gRenderQI.t + pos, texCoord, sizeof(texCoord) );
	gRenderQI.count++;
}
void ASprite::AddFrm(T_S32 frame, T_S32 posX, T_S32 posY, T_S32 flags, T_S32 hx, T_S32 hy)
{
	int nFModules = _frames_nfm[frame]&0xFF;	
	//Rect2D _frame_rect;
	//memset( &_frame_rect, 0, sizeof(Rect2D) );
	for (int fmodule = 0; fmodule < nFModules; fmodule++)
	{
		AddFModule( frame, fmodule, posX, posY, flags );
	}
	//int target_fw = _frame_rect.w;
	//int target_fh = _frame_rect.h;/
}
void ASprite::EndBatchFrm()
{
	if(gRenderQI.count==0)
		return;
	g2DCommRI.tex = (TexInfo*)getTexMgr()->GetTex( _img[_crt_img] );
	//ASSERT( g2DCommRI.tex );
	if( g2DCommRI.tex == NULL )
		return;
	_gfx->Flush2D();
}

#else
void ASprite::PaintFrame(int frame, int posX, int posY, int flags, int hx, int hy)
{
	if(frame == -1) return;
	ASSERT(frame>=0 && frame < _nFrames)
    int nFModules = _frames_nfm[frame]&0xFF;
	_f_ox_if = 0;//_frames_rc[frame*4 + 0] + (_frames_rc[frame*4 + 2]&0xFF)/2;
	_f_oy_if = 0;//_frames_rc[frame*4 + 1] + (_frames_rc[frame*4 + 3]&0xFF)/2;

    for (int fmodule = 0; fmodule < nFModules; fmodule++)
	{
        PaintFModule( frame, fmodule, posX, posY, flags, hx, hy );
	}
}

void ASprite::PaintFModule(int frame, int fmodule, int posX, int posY, int flags, int hx, int hy)
{
	int off = (_frames_fm_start[frame] + fmodule) * 6; // laevo: BS_FM_OFF_SHORT
	int fm_flags = _fmodules[off+5]&0xFF;
	int index = _fmodules[off]&0xFF;
	int ox = (_fmodules[off + 1] & 0xFF) | ((_fmodules[off + 2]) << 8);
	int oy = (_fmodules[off + 3] & 0xFF) | ((_fmodules[off + 4]) << 8);
	_m_x_if = ox;
	_m_y_if = oy;
	if( g2DCommRI.anchorType == Is_MultiFrameCenter )
	{
		_m_x_if += (posX - g2DCommRI.oX_is);
		_m_y_if += (posY - g2DCommRI.oY_is);
		posX = g2DCommRI.oX_is;
		posY = g2DCommRI.oY_is;
	}
	if( !cGfx::IsHVCenter() )
	{
		if ((flags & FLAG_FLIP_X) != 0)
			posX -= ox;
		else
			posX += ox;
		if ((flags & FLAG_FLIP_Y) != 0)
			posY -= oy;
		else
			posY += oy;
	}

	if (USE_HYPER_FM && ((fm_flags & FLAG_HYPER_FM) != 0))
	{
		PaintFrame( index, posX, posY, flags ^ (fm_flags&0x0F), hx, hy );
	}
	else
	{
		if ((flags & FLAG_FLIP_X) != 0)	posX -= _modules_w[index]&0xFFFF;
		if ((flags & FLAG_FLIP_Y) != 0)	posY -= _modules_h[index]&0xFFFF;

		_PaintModule( index, posX, posY, flags ^ (fm_flags&0x0F) );
	}
}

void ASprite::_PaintModule(int module, int posX, int posY, int flags)
{
	/*if( USE_MODULE_MAPPINGS )
	{
		if (_cur_map >= 0)
		{
			module = _map[_cur_map][module];
		}
	}*/

	int modX = _modules_x[module]&0xFFFF;
	int modY = _modules_y[module]&0xFFFF;
	int modW = _modules_w[module]&0xFFFF;
	int modH = _modules_h[module]&0xFFFF;
	if( modW <= 0 || modH <= 0 ) return;
	if( _img_num*_nModules < _crt_img * _nModules + module )
		return;

	int _modW = modW;
	int _modH = modH;
	if( flags & FLAG_ROT_90 )
		SWAP( _modW, _modH );
	GFX_SetAnchor( -(_f_ox_if - _m_x_if) + _modW/2, (_f_oy_if - _m_y_if) - _modH/2, anchor_frm );
	_gfx->DrawRegion(getTexMgr()->GetTex( _img[_crt_img] ), posX, posY, modX, modY, modW, modH, flags );
	GFX_ClearAnchor( anchor_frm );
}
#endif

#ifdef _TestEnable
void ASprite::PaintModule(int frame, int posX, int posY, int flags, int hx, int hy)
{
	//gImgBuffer
}
#endif
void ASprite::PaintFModule(int frame, int index, int posX, int posY, int flags)
{
	int off = (_frames_fm_start[frame] + index) * 6; // laevo: BS_FM_OFF_SHORT
	int fm_flags = _fmodules[off+5]&0xFF;
	//int index = _fmodules[off]&0xFF;
	posX += (_fmodules[off + 1] & 0xFF) | ((_fmodules[off + 2]) << 8);
	posY += (_fmodules[off + 3] & 0xFF) | ((_fmodules[off + 4]) << 8);

	int modX = _modules_x[index]&0xFFFF;
	int modY = _modules_y[index]&0xFFFF;
	int modW = _modules_w[index]&0xFFFF;
	int modH = _modules_h[index]&0xFFFF;

#ifdef USE_BS_MODULES_IMG
	_gfx->DrawRegion(getTexMgr()->GetTex( _img[_modules_img_index[index]] ), posX, posY, modX, modY, modW, modH, flags );
#else
	_gfx->DrawRegion(getTexMgr()->GetTex( _img[_crt_img] ), posX, posY, modX, modY, modW, modH, flags );
#endif
}
void ASprite::PaintModule(int module, int posX, int posY, int flags)
{
	GLfloat tL, tB, tR,tT, vL,vB, vR, vT;
	//@brief frame offset is short type
	//int off = (_frames_fm_start[frame] + indexf) * 6; // laevo: BS_FM_OFF_SHORT
	//int fm_flags = _fmodules[off+5]&0xFF;
	//laevo:M 20070716
	//@brief 1L is for breaking the limit of module num per frame (less 256)
	//          but must fmodule index agree with module index. (for example jp font index)
	//int index = (indexf>255)?(indexf):(_fmodules[off]&0xFF);
	int ox = 0;//(_fmodules[off + 1] & 0xFF) | ((_fmodules[off + 2]) << 8);
	int oy = 0;//(_fmodules[off + 3] & 0xFF) | ((_fmodules[off + 4]) << 8);

	//int target_dx = posX;
	//int target_dy = posX;
	g2DCommRI.destX = posX;
	g2DCommRI.destY = SCREEN_HEIGHT - posY;
	gRenderQI.count = 0;
	//if( (flags & FLAG_FLIP_X) != 0 )
	//	ox = -ox - _modules_w[module]&0xFFFF;
	//if ((flags & FLAG_FLIP_Y) != 0 )
	//	oy = -oy - _modules_h[module]&0xFFFF;
	int _flags = flags;
	//_flags ^= (fm_flags&0x0F);

	int modX = _modules_x[module]&0xFFFF;
	int modY = _modules_y[module]&0xFFFF;
	int modW = _modules_w[module]&0xFFFF;
	int modH = _modules_h[module]&0xFFFF;
	if( modW <= 0 || modH <= 0 ) return;
	if( _img_num*_nModules < _crt_img * _nModules + module )
		return;

	int target_mw = modW;
	int target_mh = modH;
	if( _flags & FLAG_ROT_90 )
	{
		target_mw = modH;
		target_mh = modW;
	}

	int _offsetL = 0;
	int _offsetB = 0-target_mh;
	int _offsetR = 0+target_mw;
	int _offsetT = 0;

	/*if( g2DCommRI.anchorType == Is_Center_LT2HV )
	{
	_offsetL = -target_mw/2;
	_offsetB = -target_mh/2;
	_offsetR = -_offsetL;
	_offsetT = -_offsetB;
	}*/
	if( _bNeedFixed && (g2DCommRI.transform&IS_ROT) )
	{
		modW++; modH++;
	}
	if( _flags & cGfx::HV_CENTER )
	{
		ox -= modW /2;
		oy -= modH /2;
	}

	//ox += posX;
	//oy += posY;

	vL = IPLMath_IntToFixed(  ox + _offsetL );
	vB = IPLMath_IntToFixed( -oy + _offsetB );
	vR = IPLMath_IntToFixed(  ox + _offsetR );
	vT = IPLMath_IntToFixed( -oy + _offsetT );

	//GLfloat autoZ = 0;
	GLfloat vertices[] =
	{
		vL, vT, 0,  // Left-Top
		vL, vB, 0,  // Left-Bottom
		vR, vB, 0,  // Right-Bottom
		vL, vT, 0,  // Left-Top
		vR, vB, 0,  // Right-Bottom
		vR, vT, 0,  // Right-Top
	};

	//tL = IPLMath_IntToFixed( modX );
	//tT = IPLMath_IntToFixed( modY );
	//tR = IPLMath_IntToFixed( modX + modW);
	//tB = IPLMath_IntToFixed( modY + modH);
	// RUIZD: Now we use real values (hardcoded removed)
	TexInfo * pInfo = (TexInfo*)getTexMgr()->GetTex( _img[_crt_img] );
	
	tL = (float)modX / (float)pInfo->width;
	tT = (float)modY / (float)pInfo->height;
	tR = (float)(modX + modW) / (float)pInfo->width;
	tB = (float)(modY + modH) / (float)pInfo->height;

	GLfloat texCoord[] =
	{
		tL, tT,
		tL, tB,
		tR, tB,
		tL, tT,
		tR, tB,
		tR, tT,
	};
	if( _flags & FLAG_FLIP_X )
	{
		texCoord[0] = texCoord[2] = tR;
		texCoord[4] = texCoord[6] = tL;
	}
	if( _flags & FLAG_FLIP_Y )
	{
		texCoord[1] = texCoord[7] = tT;
		texCoord[3] = texCoord[5] = tB;
	}
	if( _flags & FLAG_ROT_90 )
	{
		GLfloat _tempX, _tempY;
		_tempX = texCoord[6]; _tempY = texCoord[7];
		texCoord[6] = texCoord[4]; texCoord[7] = texCoord[5];
		texCoord[4] = texCoord[2]; texCoord[5] = texCoord[3];
		texCoord[2] = texCoord[0]; texCoord[3] = texCoord[1];
		texCoord[0] = _tempX; texCoord[1] = _tempY;
	}
#ifdef IPL_HAVE_MESSED_UP_QUADS
	GLfloat _tempX, _tempY;
	_tempX = texCoord[4]; texCoord[4] = texCoord[6]; texCoord[6] = _tempX;
	_tempY = texCoord[5]; texCoord[5] = texCoord[7]; texCoord[7] = _tempY;
#endif
	int pos = gRenderQI.count*12;
	MEMCPY( gRenderQI.v + pos, vertices, sizeof(vertices) );
	pos = gRenderQI.count*8;
	MEMCPY( gRenderQI.t + pos, texCoord, sizeof(texCoord) );
	gRenderQI.count++;

	g2DCommRI.tex = (TexInfo*)getTexMgr()->GetTex( _img[_crt_img] );
	_gfx->Flush2D();

//#ifdef USE_BS_MODULES_IMG
//	_gfx->DrawRegion(getTexMgr()->GetTex( _img[_modules_img_index[module]] ), posX, posY, modX, modY, modW, modH, flags );
//#else
//	_gfx->DrawRegion(getTexMgr()->GetTex( _img[_crt_img] ), posX, posY, modX, modY, modW, modH, flags );
//#endif
}

bool ASprite::BeginFrmOutIn(int objIdx, T_F32 inScale, int ox, int oy)
{
#ifdef _USE_ANSWER_SCALE
	_curScale = inScale;
	_curFrmOutIn = 0;
	bool result = false;
	if( (_objSelected != objIdx)/* && (_DrawObjSelectedCount == FRM_OutIn_Count) */)
	{
		_DrawObjSelectedCount = -10;
		_objSelected = objIdx;
	}
	//T_F32 _scale = _inScale;
	if( _DrawObjSelectedCount < FRM_OutIn_Count )
	{
		_curScale = inScale * (1.2f - CMath::Abs(_DrawObjSelectedCount) / 20.0f);
		_DrawObjSelectedCount += FRM_OutIn_Step;
	}
	else
		result = true;
	GFX_SetScale( _curScale, _curScale, ox, oy );
	return result;
#else
	return true;
#endif
}
//void ASprite::PaintFrmOutIn(int frame, int posX, int posY)
//{		
//	PaintFrame( frame, posX, posY );	
//}
void ASprite::EndFrmOutIn()
{
	GFX_ResetScale();
}

void ASprite::PaintModuleIn3D(int module, int posX, int posY)
{
#ifdef USE_MODULE_MAPPINGS
	if (_cur_map >= 0)
	{
		module = _map[_cur_map][module];
	}
#endif //USE_MODULE_MAPPINGS

	int modX = _modules_x[module]&0xFFFF;
	int modY = _modules_y[module]&0xFFFF;
	int modW = _modules_w[module]&0xFFFF;
	int modH = _modules_h[module]&0xFFFF;
	if( modW <= 0 || modH <= 0 ) return;
	if( _img_num*_nModules < _crt_img * _nModules + module )
		return;	
	
	g3DCommRI.destX = posX;
	g3DCommRI.destY = posY;
	g3DCommRI.modX = modX;
	g3DCommRI.modY = modY;
	g3DCommRI.modW = modW;
	g3DCommRI.modH = modH;
	g3DCommRI.tex = (TexInfo*)getTexMgr()->GetTex( _img[_crt_img] );

	_gfx->DrawRegionIn3D( g3DCommRI );
}
bool ASprite::PaintFrmUD(int frame, int posX, int posY)
{
	/*T_F32 _scale = 1.0f;
	if( _frmCounter < 20 - 10 )
		_scale = 0.0f;
	else if( _frmCounter < 20 - 5 )
		_scale = (T_F32)(_frmCounter - 20 + 10) / 5;
	GFX_SetScale( 1.0f, _scale );
	PaintFrame( frame, 160, 135 );
	GFX_ResetScale();*/
	return true;
}
void ASprite::PaintFrameIn3D(int frame, int posX, int posY, int flags, int hx, int hy)
{
	ASSERT(frame>=0 && frame <= _nFrames);
	int nFModules = _frames_nfm[frame]&0xFF;

	GLfloat tL, tB, tR,tT, vL,vB, vR, vT;
	gRenderQI.count = 0;

	Rect2D _frame_rect;
	memset( &_frame_rect, 0, sizeof(Rect2D) );
	for (int fmodule = 0; fmodule < nFModules; fmodule++)
	{
		int off = (_frames_fm_start[frame] + fmodule) * 6; // laevo: BS_FM_OFF_SHORT
		int fm_flags = _fmodules[off+5]&0xFF;
		int index = _fmodules[off]&0xFF;
		int ox = (_fmodules[off + 1] & 0xFF) | ((_fmodules[off + 2]) << 8);
		int oy = (_fmodules[off + 3] & 0xFF) | ((_fmodules[off + 4]) << 8);

		int target_dx = posX;
		int target_dy = posX;
		if( (flags & FLAG_FLIP_X) != 0 )
			ox = -ox - _modules_w[index]&0xFFFF;
		if ((flags & FLAG_FLIP_Y) != 0 )
			oy = -oy - _modules_h[index]&0xFFFF;
		int _flags = flags;
		_flags ^= (fm_flags&0x0F);

		int modX = _modules_x[index]&0xFFFF;
		int modY = _modules_y[index]&0xFFFF;
		int modW = _modules_w[index]&0xFFFF;
		int modH = _modules_h[index]&0xFFFF;
		if( modW <= 0 || modH <= 0 ) return;
		if( _img_num*_nModules < _crt_img * _nModules + index )
			return;

		int target_mw = modW;
		int target_mh = modH;
		if( _flags & FLAG_ROT_90 )
		{
			target_mw = modH;
			target_mh = modW;
		}

		T_F32 _offsetL = 0.0f;
		T_F32 _offsetB = (T_F32) -target_mh;
		T_F32 _offsetR = (T_F32) target_mw;
		T_F32 _offsetT = 0.0f;
		if( g2DCommRI.anchorType == Is_Center_LT2HV )
		{
			_offsetL = -(T_F32)target_mw/2;
			_offsetB = -(T_F32)target_mh/2;
			_offsetR = -_offsetL;
			_offsetT = -_offsetB;
		}
		vL = IPLMath_FloatToFixed(  ox + _offsetL );
		vB = IPLMath_FloatToFixed( -oy + _offsetB );
		vR = IPLMath_FloatToFixed(  ox + _offsetR );
		vT = IPLMath_FloatToFixed( -oy + _offsetT );

		//int autoZ = 0;
		GLfloat vertices[] =
		{
			vL, vB, 0, //1.0f,
			vL, vT, 0, //1.0f,
#ifdef IPL_HAVE_MESSED_UP_QUADS
			vR, vB, 0, //1.0f,
			vR, vT, 0, //1.0f
#else
			vR, vT, 0, //1.0f,
			vR, vB, 0, //1.0f
#endif
		};

		tL = IPLMath_IntToFixed( modX );
		tT = IPLMath_IntToFixed( modY );
		tR = IPLMath_IntToFixed( modX + modW );
		tB = IPLMath_IntToFixed( modY + modH );
		GLfloat texCoord[] =
		{
			tL, tB,
			tL, tT,
			tR, tT,
			tR, tB
		};
		if( _flags & FLAG_FLIP_X )
		{
			texCoord[0] = texCoord[2] = tR;
			texCoord[4] = texCoord[6] = tL;
		}
		if( _flags & FLAG_FLIP_Y )
		{
			texCoord[1] = texCoord[7] = tT;
			texCoord[3] = texCoord[5] = tB;
		}
		if( _flags & FLAG_ROT_90 )
		{
			GLfloat _tempX, _tempY;
			_tempX = texCoord[6]; _tempY = texCoord[7];
			texCoord[6] = texCoord[4]; texCoord[7] = texCoord[5];
			texCoord[4] = texCoord[2]; texCoord[5] = texCoord[3];
			texCoord[2] = texCoord[0]; texCoord[3] = texCoord[1];
			texCoord[0] = _tempX; texCoord[1] = _tempY;
		}
#ifdef IPL_HAVE_MESSED_UP_QUADS
		GLfloat _tempX, _tempY;
		_tempX = texCoord[4]; texCoord[4] = texCoord[6]; texCoord[6] = _tempX;
		_tempY = texCoord[5]; texCoord[5] = texCoord[7]; texCoord[7] = _tempY;
#endif

		int pos = gRenderQI.count*12;
		MEMCPY( gRenderQI.v + pos, vertices, sizeof(vertices) );
		pos = gRenderQI.count*8;
		MEMCPY( gRenderQI.t + pos, texCoord, sizeof(texCoord) );
		gRenderQI.count++;
	}

	g3DCommRI.destX = posX;
	g3DCommRI.destY = SCREEN_HEIGHT - posY;
	g3DCommRI.tex = (TexInfo*)getTexMgr()->GetTex( _img[_crt_img] );
	ASSERT( g3DCommRI.tex );
	_gfx->Flush3D();
}

int * ASprite::GenPalette(int type, int * pal, int length) //length == pal.length
{
    if (type <  0) return pal;
    if (type == 0) return NULL;

    int* NEW_pal = GL_NEW int[length];
    switch (type)
    {
    case 4:
        for (int i = 0; i < length; i++)
        {
            int a = (pal[i] & 0xFF000000);
            int r = (pal[i] & 0x00FF0000) >> 16;
            int g = (pal[i] & 0x0000FF00) >> 8;
            int b = (pal[i] & 0x000000FF);
            int l = ((r + b + g) / 3) & 0x000000FF;
            NEW_pal[i] = ((l << 16) | (l << 8) | l | a);
        }
        break;
	}

    return NEW_pal;
}

int ASprite::DrawNumber(int x, int y, int number, int frame_0, int Align, bool percent, int gap)
{
	#define DRAWNUMBER_MAX_DIGITS 10
	const int num_spacing_w = 0;
	int n[DRAWNUMBER_MAX_DIGITS], ln = 0;
	int num_width = 0;

	if (number == 0)
	{
		n[0] = 0;
		ln = 1;
		num_width += GetFrameWidth(frame_0) + num_spacing_w + gap;
	} 
	else
	{
		while (number > 0 && ln < DRAWNUMBER_MAX_DIGITS)
		{
			n[ln] = number % 10;
			number -= n[ln];
			number /= 10;

			num_width += GetFrameWidth( frame_0 + n[ln]) + num_spacing_w + gap;
			ln++;
		}
		num_width -= num_spacing_w + gap;
		ASSERT(ln < DRAWNUMBER_MAX_DIGITS);
	}

	if (percent)
	{
		num_width += GetFrameWidth( frame_0 + 10) + num_spacing_w + gap;
	}
	
	int xNum = x;
	if (Align & (1<<4))
	{
		if (Align &  (1<<1))
		{
			//Center
			xNum -= (num_width>>1);
		}
		else
		{
			//Right
			xNum -= num_width;
		}
	}
	//Note: not Aligned to Y

	for (int i = 0; i < ln; i++)
	{
		PaintFrame( frame_0 + n[ln - i-1], xNum, y);
		xNum += GetFrameWidth( frame_0 + n[ln-i-1]) + num_spacing_w + gap;
	}

	if (percent)
	{
		PaintFrame( frame_0 + 10, xNum, y);
		xNum += GetFrameWidth( frame_0 + 10) + num_spacing_w + gap;
	}
	
	return xNum;
}

void ASprite::SetCurrentPalette(int pal)	{ _crt_img = pal; }
int  ASprite::GetCurrentPalette()			{ return _crt_img; }
int  ASprite::GetCurrentTexIndex()			{ return _img[_crt_img];}
//int ASprite::_loadImageData(char* file, int offset)
//{
//#ifdef USE_BSPRITE_FLAGS
//	//////////////////////////////
//	// BSprite version...
//	short bs_version = (short)((file[offset]&0xFF) + ((file[offset+1]&0xFF)<<8)); offset += 2;
//	ASSERT(bs_version == BSPRITE_v003, "Invalid BSprite version!");
//
//	// BSprite filter flags...
//	_bs_flags = ((file[offset  ]&0xFF)    ) +
//		((file[offset+1]&0xFF)<< 8) +
//		((file[offset+2]&0xFF)<<16) +
//		((file[offset+3]&0xFF)<<24);
//	offset += 4;
//#endif
//
//	// Pixel format (must be one of supported SPRITE_FORMAT_xxxx)...
//	_pixel_format = (short)((file[offset] & 0xFF) + ((file[offset+1] & 0xFF) << 8));
//	offset+=2;
//
//	// Number of palettes...
//	_palettes = file[offset++] & 0xFF;
//
//	// Number of colors...
//	_colors = file[offset++] & 0xFF;			 
//
//#ifdef USE_ENCODE_FORMAT_I256
//	if (_colors == 0) _colors = 256; // for I256
//#endif //USE_ENCODE_FORMAT_I256
//
//
//	//_alpha_index = -1;
//
//	//////////////////////////////
//	// Palettes...
//	_pal = GL_NEW T_PAL[_palettes * _colors];			
//	for (int p = 0; p < _palettes; p++)
//	{			
//		for (int c = 0; c < _colors; c++)
//		{
//			if (_pixel_format == PIXEL_FORMAT_8888)
//			{
//				int iBlue	= file[offset++] & 0xff;
//				int iGreen	= file[offset++] & 0xff;
//				int iRed	= file[offset++] & 0xff;
//				int iAlpha	= file[offset++] & 0xff;
//
//				if (iAlpha != 0xFF)
//					_alpha = true;
//				_pal[p*_colors + c] = (iAlpha << 24) | (iRed << 16) | (iGreen << 8) | iBlue;
//			}
//			else if (_pixel_format == PIXEL_FORMAT_0565)
//			{
//				int _0565 = ((file[offset++] & 0xFF));
//				_0565 += ((file[offset++] & 0xFF) << 8);
//
//				int a = 0xFF000000;
//				if (_0565 == 0xF81F)
//				{
//					a = 0;
//					_alpha = true;
//				}						
//
//				_pal[p*_colors + c] = (
//					a |							// A
//					((_0565 & 0xF800) << 8) |	// R
//					((_0565 & 0x07E0) << 5) |	// G
//					((_0565 & 0x001F) << 3));	// B
//			}
//		}
//	}
//
//	//////////////////////////////
//	// Data format (must be one of supported ENCODE_FORMAT_xxxx)...
//	_data_format = (short)((file[offset] & 0xFF) + ((file[offset+1] & 0xFF) << 8));offset+=2;
//
//#ifdef USE_ENCODE_FORMAT_I64RLE
//	if (_data_format == ENCODE_FORMAT_I64RLE)
//	{
//		int clrs = _colors - 1;
//		_i64rle_color_mask = 1;
//		_i64rle_color_bits = 0;
//		while (clrs != 0)
//		{
//			clrs >>= 1;
//			_i64rle_color_mask <<= 1;
//			_i64rle_color_bits++;
//		}
//		_i64rle_color_mask--;
//	}
//#endif //USE_ENCODE_FORMAT_I64RLE
//
//	// Graphics data...
//	if (_nModules > 0)
//	{
//		_modules_data_off = GL_NEW int[_nModules];
//		int len = 0;
//		int off = offset;
//
//		for (int m = 0; m < _nModules; m++)
//		{
//			// Image data for the module...
//			int size = (file[off] & 0xFF) + ((file[off+1] & 0xFF) << 8);
//
//			_modules_data_off[m] = /*(short)*/len;
//			off += size+2;
//			len += size;
//		}
//
//		_modules_data = GL_NEW u8[len];
//		_modules_data_length = len;
//		for (int m = 0; m < _nModules; m++)
//		{
//			// Image data for the module...
//			int size = (file[offset] & 0xFF) + ((file[offset+1] & 0xFF) << 8);offset+=2;					
//			ArrayCopy(file, offset, _modules_data, _modules_data_off[m]/* & 0xFFFF*/, size);
//			offset += size;
//		}
//	}
//
//	//////////////////////////////
//	// module mappings
//#ifdef USE_MODULE_MAPPINGS
//	_cur_map = -1;
//	_map_length = 0;
//#endif //USE_MODULE_MAPPINGS
//	return offset;
//}